import { _decorator, Animation, Color, Component, find, instantiate, Label, Node, Prefab, ProgressBar, Sprite, SpriteFrame, tween, v3, Vec3 } from 'cc';
import { OperationItem } from '../entity/OperationItem';
import { em_Effect_Comm, HeroConfig } from '../settings/const';
import { Hero } from '../entity/Hero';
import { Utils } from '../common/Utils';
import { TextTip } from './TextTip';
import { AttrChangedType } from '../entity/AttrChangedType';
import { Skill, SkillArray } from '../entity/Skill';
import { BattleBuffEnum } from '../entity/BattleBuffEnum';
import { NotifyEnum } from '../entity/NotifyEnum';
import ResManager from '../common/ResManager';
import { PrefabEnum } from '../common/PrefabEnum';
import { TargetLine } from './TargetLine';
import { FightController } from './FightController';
import { EffectEnum, EffectManager } from '../common/EffectManager';
import { UserInfo } from '../common/UserInfo';
import { UIManager } from '../common/UIManager';
const { ccclass, property } = _decorator;

@ccclass('CardController')
export class CardController extends Component {
    @property(Animation)
    blank: Animation
    @property(Sprite)
    heroImg: Sprite
    @property(ProgressBar)
    hp: ProgressBar

    @property(Label)
    heroName: Label
    @property(Label)
    per: Label
    @property(Sprite)
    mubei: Sprite

    @property(Prefab)
    textTip: Prefab
    @property(Prefab)
    buffLabel: Prefab
    @property(Node)
    buffLayout: Node

    public userId: number
    public heroId: number
    public position: number
    public attack: number
    public life: number = 0
    public maxLife: number = 0
    public morale: number
    public hero: Hero

    start() {

    }

    async setData(op: OperationItem) {
        this.userId = op.params.sInfo[0]
        this.heroId = op.params.sInfo[1]
        this.position = op.params.sInfo[2]

        this.attack = op.params.value.a
        this.life = op.params.value.d
        this.maxLife = op.params.value.dm
        this.morale = op.params.value.h

        this.hero = Hero.create(HeroConfig[this.heroId])
        console.log(this.hero.star)

        this.scheduleOnce(() => {
            let name = this.blank.clips[this.hero.star - 1].name
            this.blank.play(name)

        }, 0.5)



        this.hp.progress = this.life / this.maxLife
        this.per.string = Math.floor((this.life / this.maxLife) * 100) + '%'
        this.heroName.string = this.hero.name

        let sf = await ResManager.instance.loadAssetByUrl<SpriteFrame>(`heroHead/${this.hero.id}/spriteFrame`)
        this.heroImg.spriteFrame = sf
    }

    async playReady(op: OperationItem) {
        this.setToTop()
        tween(this.node)
            .to(0.2, { scale: new Vec3(1.5, 1.5, 1.5) },)

            .start()

        UIManager.instance.addTextTip(
            `${SkillArray[op.params.type].name}`,
            Color.GREEN,
            this.node.worldPosition)




        await this.waitForSecond(0.5)
    }

    async playStart(op: OperationItem) {
        let pos = this.node.getPosition()
        tween(this.node)

            .to(0.2, { position: v3(pos.x, pos.y + 30, pos.z) })
            .to(0.2, { position: pos })
            .start()

        for (let item of op.params.sim) {
            let userId = item[0]
            let heroId = item[1]
            let index = item[2]

            let target = FightController.instance.getCard(userId, heroId)
            if (!target) {
                continue
            }

            if (userId == this.userId) {
                // 给队友释放技能
                Skill.playAddition(target.worldPosition)
            } else {
                // 给敌人释放技能
                let isBang = FightController.instance.isBang(op.EventIndex, heroId)
                Skill.playSkill(this.node.worldPosition, target.worldPosition, isBang)
            }




        }
        await this.waitForSecond(0.5)
    }
    async playCancel(op: OperationItem) {
        tween(this.node)
            .to(0.5, { scale: new Vec3(1, 1, 1) },)
            .start()
        await this.waitForSecond(0.5)
    }
    async playEnd(op: OperationItem) {
        tween(this.node)
            .to(0.5, { scale: new Vec3(1, 1, 1) },)
            .start()
        await this.waitForSecond(0.5)
    }

    async playBuffChanged(op: OperationItem) {
        let userId = op.params.sInfo[0]
        let heroId = op.params.sInfo[1]
        let index = op.params.sInfo[2]
        let target = FightController.instance.getCard(userId, heroId)

        tween(this.node)
            .to(0.2, { scale: new Vec3(1, 1, 1) },)

            .start()
        this.shake()

        let text = ''
        if (op.params.count > 0) {
            text = `${BattleBuffEnum.StatusName(op.params.type)}`;
            this.addBuff(BattleBuffEnum.StatusName(op.params.type))
            await Skill.buff(target.worldPosition, op.params.type)
        }
        else if (op.params.count == -1) {
            text = `${BattleBuffEnum.StatusName(op.params.type)}`;
            this.addBuff(BattleBuffEnum.StatusName(op.params.type))
            await Skill.buff(target.worldPosition, op.params.type)
        }
        else {
            text = `${BattleBuffEnum.StatusName(op.params.type)}失效`;
            this.removeBuff(BattleBuffEnum.StatusName(op.params.type))
        }

        UIManager.instance.addTextTip(
            text,
            Color.YELLOW,
            this.node.worldPosition)

        await this.waitForSecond(0.5)
    }



    async playAttrChanged(op: OperationItem) {
        this.shake()



        let damage = this.life - op.params.value.d

        this.attack = op.params.value.a
        this.life = op.params.value.d
        this.maxLife = op.params.value.dm
        this.morale = op.params.value.h
        this.hp.progress = this.life / this.maxLife
        this.per.string = Math.floor((this.life / this.maxLife) * 100) + '%'

        let userId = op.params.sInfo[0]
        let heroId = op.params.sInfo[1]
        let index = op.params.sInfo[2]
        let target = FightController.instance.getCard(userId, heroId)
        await Skill.hurt(target.worldPosition, op.params.type)

        if(op.params.type == AttrChangedType.Recover){
            UIManager.instance.addTextTip(
                `${AttrChangedType.TypeStr(op.params.type)}+${-damage}`,
                Color.GREEN,
                this.node.worldPosition)
        } else {
            UIManager.instance.addTextTip(
                `${AttrChangedType.TypeStr(op.params.type)}-${damage}`,
                Color.RED,
                this.node.worldPosition)
        }
        

    }

    async playDead(op: OperationItem) {
        // tween(this.node)
        //     .to(0.5, { scale: v3(0.8, 0.8, 0.8) },)
        //     .start()

        for (let item of this.node.children) {
            item.active = false
        }
        this.mubei.node.active = true

        tween(this.mubei.node)
            .to(0, { position: v3(0, 300, 0) })
            .to(0.2, { position: v3(0, 0, 0) }, {
                onComplete: () => {
                    let pos = this.mubei.node.worldPosition.subtract(v3(0, 50, 0))
                    EffectManager.instance.playOnce(EffectEnum.YunChen, pos)
                }
            })
            .start()



    }

    async playAlive(op: OperationItem) {
        tween(this.node)
            .to(0.5, { scale: v3(1, 1, 1) },)
            .start()


        this.hp.node.active = true
        this.hp.progress = 1
        this.per.string = '100%'

        for (let item of this.node.children) {
            item.active = true
        }
        this.mubei.node.active = false

        UIManager.instance.addTextTip(
            '复活',
            Color.GREEN,
            this.node.worldPosition)
    }

    async playCombo(op: OperationItem) {
        UIManager.instance.addTextTip(
            `连击${op.params.value}`,
            Color.GREEN,
            this.node.worldPosition)


    }

    async playComboReady(op: OperationItem) {
        UIManager.instance.addTextTip(
            `发动了连击`,
            Color.GREEN,
            this.node.worldPosition)
    }

    async playEffect(op: OperationItem) {
        let text = ''
        if (op.params.global) {
            text = `全局${em_Effect_Comm[op.params.type].name}/${op.params.value.toFixed(2)}`;
        }
        else {
            text = `${em_Effect_Comm[op.params.type].name}/${op.params.value.toFixed(2)}`;
        }
        UIManager.instance.addTextTip(
            text,
            Color.GREEN,
            this.node.worldPosition)
    }

    async playNotify(op: OperationItem) {
        UIManager.instance.addTextTip(
            `${NotifyEnum.StatusName(op.params.type)}`,
            Color.GREEN,
            this.node.worldPosition)
    }

   

    waitForSecond(sec: number) {
        return new Promise((resolve) => {
            this.scheduleOnce(() => {
                resolve(1)
            }, sec)
        })
    }

    /**置顶 */
    setToTop() {
        return

        let parent = this.node.parent
        for (let i = 0; i < parent.children.length; i++) {
            let ch = parent.children[i]
            ch.setSiblingIndex(i)
        }
        this.node.setSiblingIndex(parent.children.length)

        parent = this.node.parent.parent
        for (let i = 0; i < parent.children.length; i++) {
            let ch = parent.children[i]
            ch.setSiblingIndex(i)
        }
        this.node.parent.setSiblingIndex(parent.children.length)
    }

    addBuff(str: string) {
        let have = false
        for (let ch of this.buffLayout.children) {
            let buff = ch.getComponent(Label).string
            if (str == buff) {
                have = true
            }
        }
        if (!have) {
            let node = instantiate(this.buffLabel)
            node.getComponent(Label).string = str
            this.buffLayout.addChild(node)
        }
    }

    removeBuff(str: string) {
        console.log('remove buff...')
        for (let ch of this.buffLayout.children) {
            let buff = ch.getComponent(Label).string

            if (str == buff) {
                console.log('destroy...')
                ch.destroy()
            }
        }
    }

    shake(){
        let pos = this.node.getPosition()
        tween(this.node)
            .to(0.3, { position: new Vec3(pos.x - 10, pos.y, pos.z) },)
            .to(0.3, { position: new Vec3(pos.x + 10, pos.y, pos.z) },)
            .to(0.2, { position: new Vec3(pos.x - 10, pos.y, pos.z) },)
            .to(0.2, { position: new Vec3(pos.x + 10, pos.y, pos.z) },)
            .to(0.1, { position: new Vec3(pos.x - 10, pos.y, pos.z) },)
            .to(0.1, { position: new Vec3(pos.x, pos.y, pos.z) },)
            .start()
    }
}


